<?php

namespace extend\docker;

use Swoole\Coroutine\Http\Client;
use zhanshop\App;

class EngineApi
{
    protected $host = '127.0.0.1';
    protected $port = 0;
    protected $ssl = false;
    protected $header = [
        'Host' => '127.0.0.1',
        'Accept' => '*'
    ];
    protected $config = [
        'timeout' => 30,
    ];
    protected $upload = [];

    public function __construct()
    {
        $host = App::env()->get('DOCKER_HOST', '/var/run/docker.sock');
        if(strpos($host, '.sock') !== false){
            $this->host = 'unix:/'.$host;
            $this->header['Host'] = '127.0.0.1';
        }else{
            if(strpos($host, 'http') === 0){
                $urls = parse_url($host);
                $port = $urls['port'] ?? 0;
                if($port == false){
                    if($urls['scheme'] == 'http'){
                        $this->port = 80;
                    }else{
                        $this->port = 443;
                    }
                }else{
                    $this->port = $port;
                }
                $this->ssl = ($urls['scheme'] == 'https') ? true : false;
                $this->host = $urls['host'];
                $this->header['Host'] = $urls['host'];
            }
        }
    }

    /**
     * 设置配置
     * @param $field
     * @param $value
     * @return $this
     */
    public function setConfig($field, $value)
    {
        $this->config[$field] = $value;
        return $this;
    }
    /**
     * 上传文件
     * @param $key
     * @param $filePath
     * @return void
     */
    public function setUpload($key, $filePath)
    {
        $this->upload[$key] = $filePath;
        return $this;
    }

    /**
     * 设置header
     * @param $key
     * @param $val
     * @return $this
     */
    public function setHeader($key, $val)
    {
        $this->header[$key] = $val;
        return $this;
    }

    /**
     * 请求
     * @param string $path
     * @param $method
     * @param string|array $data
     * @param mixed|null $callback
     * @return array
     */
    public function request(string $path, $method = "GET", string|array $data = [], mixed $callback = null)
    {
        $startTime = microtime(true);
        $client = new Client($this->host, $this->port);
        $client->set($this->config);
        if($data){
            if(is_array($data)){
                $data = json_encode($data, JSON_UNESCAPED_SLASHES + JSON_UNESCAPED_UNICODE);
                $this->header['Content-Type'] = 'application/json';
            }
            $client->setData($data);
        }
        $client->setMethod($method);
        $client->setHeaders($this->header);
        if($this->upload){
            foreach ($this->upload as $key => $filePath){
                $client->addFile($filePath, $key);
            }
        }
        $body = "";
        if($callback){
            $client->set(['write_func' => function ($client, $data) use($callback){
                $callback($client, $data);
            }]);
        }
        $client->execute($path);
        $code = $client->getStatusCode();
        if($callback == false){
            $body = $client->getBody();
        }
        $client->close();
        $outData = [
            'code' => $code,
            'header' => [],
            'body' => $body,
            'time' => microtime(true) - $startTime,
        ];
        return $outData;
    }
}